From 74bd3c3be3b93e20970f228289c814b9a518065d Mon Sep 17 00:00:00 2001 From: Andrew Gallant Date: Wed, 12 Nov 2014 21:20:44 -0500 Subject: [PATCH] Add `lto` option to profiles. Closes #759. --- src/cargo/core/manifest.rs | 18 +++++++++++++++++- src/cargo/ops/cargo_rustc/mod.rs | 15 +++++++++++---- src/cargo/util/toml.rs | 6 ++++-- tests/test_cargo_compile.rs | 30 ++++++++++++++++++++++++++++++ 4 files changed, 62 insertions(+), 7 deletions(-) diff --git a/src/cargo/core/manifest.rs b/src/cargo/core/manifest.rs index eebed5f4a..0e96a8d7b 100644 --- a/src/cargo/core/manifest.rs +++ b/src/cargo/core/manifest.rs @@ -126,6 +126,7 @@ pub enum TargetKind { pub struct Profile { env: String, // compile, test, dev, bench, etc. opt_level: uint, + lto: bool, codegen_units: Option, // None = use rustc default debug: bool, rpath: bool, @@ -143,6 +144,7 @@ impl Profile { Profile { env: String::new(), opt_level: 0, + lto: false, codegen_units: None, debug: false, rpath: false, @@ -160,6 +162,7 @@ impl Profile { Profile { env: "compile".to_string(), // run in the default environment only opt_level: 0, + lto: false, debug: true, .. Profile::default() } @@ -179,6 +182,7 @@ impl Profile { Profile { env: "bench".to_string(), opt_level: 3, + lto: false, test: true, dest: Some("release".to_string()), .. Profile::default() @@ -189,6 +193,7 @@ impl Profile { Profile { env: "release".to_string(), opt_level: 3, + lto: false, dest: Some("release".to_string()), .. Profile::default() } @@ -236,6 +241,10 @@ impl Profile { self.opt_level } + pub fn get_lto(&self) -> bool { + self.lto + } + pub fn get_codegen_units(&self) -> Option { self.codegen_units } @@ -261,6 +270,11 @@ impl Profile { self } + pub fn lto(mut self, lto: bool) -> Profile { + self.lto = lto; + self + } + pub fn codegen_units(mut self, units: Option) -> Profile { self.codegen_units = units; self @@ -315,6 +329,7 @@ impl hash::Hash for Profile { // to the actual hash of a profile. let Profile { opt_level, + lto, codegen_units, debug, rpath, @@ -332,7 +347,8 @@ impl hash::Hash for Profile { custom_build: _, } = *self; - (opt_level, codegen_units, debug, rpath, for_host, dest, harness).hash(into) + (opt_level, lto, codegen_units, debug, + rpath, for_host, dest, harness).hash(into) } } diff --git a/src/cargo/ops/cargo_rustc/mod.rs b/src/cargo/ops/cargo_rustc/mod.rs index 89f4217da..88df60d6d 100644 --- a/src/cargo/ops/cargo_rustc/mod.rs +++ b/src/cargo/ops/cargo_rustc/mod.rs @@ -320,6 +320,7 @@ fn compile_custom_old(pkg: &Package, cmd: &str, .env("TARGET", Some(cx.target_triple())) .env("DEBUG", Some(profile.get_debug().to_string())) .env("OPT_LEVEL", Some(profile.get_opt_level().to_string())) + .env("LTO", Some(profile.get_lto().to_string())) .env("PROFILE", Some(profile.get_env())); for arg in cmd { p = p.arg(arg); @@ -549,10 +550,16 @@ fn build_base_args(cx: &Context, if profile.get_opt_level() != 0 { cmd = cmd.arg("--opt-level").arg(profile.get_opt_level().to_string()); } - - match profile.get_codegen_units() { - Some(n) => cmd = cmd.arg("-C").arg(format!("codegen-units={}", n)), - None => {}, + if target.is_bin() && profile.get_lto() { + cmd = cmd.args(["-C", "lto"]); + } else { + // @alexchrichton says that there may be some restrictions with LTO + // and codegen-units, so that we should only add codegen units when + // LTO is not used. + match profile.get_codegen_units() { + Some(n) => cmd = cmd.arg("-C").arg(format!("codegen-units={}", n)), + None => {}, + } } if profile.get_debug() { diff --git a/src/cargo/util/toml.rs b/src/cargo/util/toml.rs index ffdaf9b8a..ea2797ab2 100644 --- a/src/cargo/util/toml.rs +++ b/src/cargo/util/toml.rs @@ -230,6 +230,7 @@ pub struct TomlProfiles { #[deriving(Decodable, Clone, Default)] pub struct TomlProfile { opt_level: Option, + lto: Option, codegen_units: Option, debug: Option, rpath: Option, @@ -673,11 +674,12 @@ fn normalize(libs: &[TomlLibTarget], None => return profile, }; let opt_level = toml.opt_level.unwrap_or(profile.get_opt_level()); + let lto = toml.lto.unwrap_or(profile.get_lto()); let codegen_units = toml.codegen_units; let debug = toml.debug.unwrap_or(profile.get_debug()); let rpath = toml.rpath.unwrap_or(profile.get_rpath()); - profile.opt_level(opt_level).codegen_units(codegen_units).debug(debug) - .rpath(rpath) + profile.opt_level(opt_level).lto(lto).codegen_units(codegen_units) + .debug(debug).rpath(rpath) } fn target_profiles(target: &TomlTarget, profiles: &TomlProfiles, diff --git a/tests/test_cargo_compile.rs b/tests/test_cargo_compile.rs index d8b034f4d..43c696a98 100644 --- a/tests/test_cargo_compile.rs +++ b/tests/test_cargo_compile.rs @@ -731,6 +731,36 @@ test!(missing_lib_and_bin { must be present\n")); }) +test!(lto_build { + let mut p = project("foo"); + p = p + .file("Cargo.toml", r#" + [package] + + name = "test" + version = "0.0.0" + authors = [] + lto = true + "#) + .file("src/main.rs", "fn main() {}"); + assert_that(p.cargo_process("build").arg("-v"), + execs().with_status(0).with_stdout(format!("\ +{compiling} test v0.0.0 ({url}) +{running} `rustc {dir}{sep}src{sep}lib.rs --crate-name test --crate-type bin -g \ + -C lto \ + -C metadata=[..] \ + -C extra-filename=-[..] \ + --out-dir {dir}{sep}target \ + --dep-info [..] \ + -L {dir}{sep}target \ + -L {dir}{sep}target{sep}deps` +", +running = RUNNING, compiling = COMPILING, sep = path::SEP, +dir = p.root().display(), +url = p.url(), +))); +}) + test!(verbose_build { let mut p = project("foo"); p = p -- 2.30.2